package net.mineclearance;
import java.util.ArrayList;
import java.util.Random;

class GameBut {
    int     countItems; //在所有中的编号
    int     value; //所在的位置值
    boolean mine; //是否为雷
    int     x, y; //雷的坐标
    int     state; //当前状态  0 默认 2标记为雷 1 确定是雷 3 已点开
    int     color; //表示字体颜色值
    boolean en; //当前是否已经被点开

    void setValueColor() {
        switch (value) { //颜色初始化
            case 1:
                color = 2901742;//蓝
                break;
            case 2:
                color = 4559879;//绿
                break;
            case 3:
                color = 13057834;//红
                break;
            case 4:
                color = 1592749;//蓝
                break;
            case 5:
                color = 9119757;//深蓝
                break;
            case 6:
                color = 16711927;//橙
                break;
            case 7:
                color = 16711927;//粉色
                break;
            case 8:
                color = 15752307;//紫色
                break;
            default:
                color = 0;//黑色
        }
    }
}

class GameButtons {  // 引入随机数生成器
    private Random random = new Random();  //引入java中的random类实例，用于生成随机数
    int     mine; //定义雷的数量，该变量用于存储雷的总数
    GameBut gameButs[][];//声明一个二维数组，用于存储雷区中的按钮元素
     // 构造方法，初始化雷区的宽高和雷的数量

    GameButtons(int x, int y /*雷区数目 0下标开始*/, int mine /*雷的数目*/) {
        //--------------------------------------------------雷数目设置  OK
        int tmpXY = (x + 1) * (y + 1);   //计算雷区的总格子数
        if (mine >= tmpXY * 0.8) //如果设置的雷数目超过 80%则安80%算
            this.mine = (int) (tmpXY * 0.8) + 1;  //设置雷的数量为80%的总格子数加1
        else
            this.mine = mine + 1;  //直接使用传入的雷的数量加1，将计算后的雷的数量赋值给成员变量mine
        mine = this.mine;
        //--------------------------------------------------生成雷区   OK
        GameBut gameButs[][] = new GameBut[x + 1][y + 1];  //创建一个比传入的宽高多1的二维数组，以包含边界
        //双重循环遍历雷区数组，初始化每个格子
        for (int i = 0; i < (x + 1); i++)   //外层循环，遍历性
            for (int j = 0; j < (y + 1); j++) {   //内层循环，遍历性
                //创建一个新的GameBut对象，并赋值给当前格子
                gameButs[i][j] = new GameBut();  //设置当前格子的行索引
                gameButs[i][j].countItems = i;  //初始化当前格子的值为0
                gameButs[i][j].value = 0; //初始化当前的格子的值为0
                gameButs[i][j].state = 0; //初始化当前的格子状态为未点击
                gameButs[i][j].x = i;  //设置当前格子的横坐标
                gameButs[i][j].y = j;  //设置当前格子的纵坐标
                gameButs[i][j].en = false;  //设置当前格子是否为雷的标记为false（默认不是雷）
            }
        //--------------------------------------------------在雷区中生成雷
        ArrayList arrayList = new ArrayList(); //用语存放为被刨除的元素集合
        int n = 0; //已经生成的雷数
        //双重循环遍历雷区数组，将所有元素添加到arraylist中
        for (int i = 0; i < (x + 1); i++)  //外层循环，遍历雷区的行
            for (int j = 0; j < (y + 1); j++) {  //内层循环，遍历雷区的行
                arrayList.add(gameButs[i][j]); //将当前雷区元素添加到ArrayList中
            }
        //---------产生雷
        int ranDomNumberTmp; //创建一个变量用于存放生成的随机数
        GameBut tmpGameBut;  //创建一个GameBut类型的变量，用于临时存储从ArrayList中取出的元素
        while (n != this.mine) { //当生成的雷数不等于雷的总数时，继续生成雷
            ranDomNumberTmp = ranDomNumber(arrayList.size()); //得到指定范围的随机整数
            tmpGameBut = (GameBut) arrayList.get(ranDomNumberTmp);  //使用随机数作为索引从ArrayList中取出一个元素
            tmpGameBut.mine = true;  //将取出的元素标记为雷
            arrayList.remove(ranDomNumberTmp);  //从ArrayList中移除已被标记为雷的元素
            n++;  //已生成的雷的数量加1
        }
        //--------------------------------------------------把雷区中的数值全部求出
        n = 0;  //重置n，用于计算每个元素周围的雷的数量
        for (int i = 0; i <= x; i++)  //开始外层循环，再次遍历雷区的每一行
            for (int j = 0; j <= y; j++) {  //开始内层循环，再次遍历雷区的每一行
            // 检查当前元素周围的8个相邻元素，计算雷的数量
                //x-1,y-1  x  ,y-1  x+1,y-1
                //x-1,y             x+1,y
                //x-1,y+1  x  ,y+1  x+1,y+1
                //得到 元素一周的雷数目
                //i表示X  j表示 Y
                if (gameButs[i][j].mine == true) {  //如果当前元素是雷，则将其设置为-1，并继续下一个元素
                    gameButs[i][j].value = -1;
                    continue;
                }
                if (i - 1 >= 0 & j - 1 >= 0 && gameButs[i - 1][j - 1].mine == true)
                    //x-1,y-1
                    n++;  //检查左上角
                if (j - 1 >= 0 && gameButs[i][j - 1].mine == true)
                    // x  ,y-1
                    n++;  //检查正上方
                if (i + 1 < x & j - 1 >= 0 && gameButs[i + 1][j - 1].mine == true)
                    // x+1,y-1
                    n++;  //检查右上角
                if (i - 1 >= 0 && gameButs[i - 1][j].mine == true)
                    //x-1,y
                    n++;  //检查左侧
                if (i + 1 < x && gameButs[i + 1][j].mine == true)
                    //x+1,y
                    n++;  //检查右侧
                if (i - 1 >= 0 & j + 1 < y && gameButs[i - 1][j + 1].mine == true)
                    //x-1,y+1
                    n++;  //检查左下角
                if (j + 1 < y && gameButs[i][j + 1].mine == true)
                    // x  ,y+1
                    n++;  //检查正下方
                if (i + 1 < x & j + 1 < y && gameButs[i + 1][j + 1].mine == true)
                    //x+1,y+1
                    n++;  //检查右下角
                gameButs[i][j].value = n;  //将计算出的雷的数量赋值给当前元素的value属性
                gameButs[i][j].setValueColor();  //假设这是一个方法，用于根据雷的数量设置元素的颜色
                n = 0;  //重置n,为下一个元素的计算做准备
            }
        this.gameButs = gameButs;  //将更新后的雷区元素集合赋值给类的gameButs属性
    }

    public int ranDomNumber(int Max) {  //定义一个方法，用于生成0到max（不包括max）之间的随机整数
        //产生Min到Max之间的随机整数
        return (int) (random.nextFloat() * Max); //使用random、nextFloat（）生成一个0到1之间的浮点数，然后乘以max并向下取整
    }
}
